/*
 * Change Logs:
 * Date           Author       Notes
 * 2022-03-27     chenbin
 */
#include "fupdate.h"
#if (FBOOT_USING_FUPDATE == 1)

#define DBG_ENABLE
#define DBG_SECTION_NAME "fupdate"
#define DBG_LEVEL DBG_INFO
#include <rtdbg.h>

#include "rbl_unpack.h"

#define LOG_NOT_EXIST(name)   LOG_E("(%s) is not exist!", name);

int fupdate_rblunpack(const char* src_name, const char* dest_name, uint32_t flags , uint32_t mode )
{
	int ret = 0;
	rbl_unpack_context_t * unpack_ctx = NULL;
	fstorage_interface_t * src_interface = NULL;
	fstorage_interface_t * dest_interface = NULL;
	
	uint32_t src_open_flags = FSTORAGE_CHECK_EXIST | FSTORAGE_READ;
	
	if( (flags & FUPDATE_FLAGS_CHECK_VERSION)  == FUPDATE_FLAGS_CHECK_VERSION )
	{
		src_open_flags |= FSTORAGE_READWRITE;  //open read write mode
	}
	
	if( (mode & FUPDATE_MODE_SRC_FAL) == FUPDATE_MODE_SRC_FAL)
	{
		src_interface = fstorage_fal_open(src_name, src_open_flags); //open fal
	}else
	if( (mode & FUPDATE_MODE_SRC_FS) == FUPDATE_MODE_SRC_FS)
	{
#if (FBOOT_USING_FILESYSTEM == 1)
		src_interface = fstorage_fs_open(src_name, src_open_flags); //open fs
#endif
	}
	if(src_interface == NULL)
	{
		LOG_NOT_EXIST(src_name);
		ret =  RBL_UNPACK_ERR_OPEN;
		goto __src_exit;
	}
	
	unpack_ctx = rbl_unpack_context_create();
	if(unpack_ctx == NULL)
	{
		ret =  RBL_UNPACK_ERR_NO_MEM;
		goto __src_exit;
	}
	unpack_ctx->src_interface = src_interface;
	
	ret = fstorage_read(unpack_ctx->src_interface, 0,  &(unpack_ctx->rbl_header) , sizeof(unpack_ctx->rbl_header));
	if(ret != sizeof(unpack_ctx->rbl_header))
	{
		ret =  RBL_UNPACK_ERR_READ;
		goto __src_exit;
	}
	
	ret = rbl_unpack_header_check( &(unpack_ctx->rbl_header));
	LOG_I("check %s header rc:%d.", src_name, ret);
	if(ret <= 0)
	{
		goto __src_exit;
	}
	
	rbl_unpack_header_show( &(unpack_ctx->rbl_header));
		
	if( (flags & FUPDATE_FLAGS_CHECK_VERSION)  == FUPDATE_FLAGS_CHECK_VERSION)
	{
		ret = rbl_unpack_header_version_check(unpack_ctx);
		if(ret == 0)
		{
			ret = RBL_UNPACK_ERR_CHECK;
			goto __src_exit;
		}
	}
	
	ret = rbl_unpack_context_buffer_init(unpack_ctx);
	if(ret < 0)
	{
		goto __buffer_exit;
	}
	
	ret = rbl_unpack_body_check(unpack_ctx);
	if(ret < 0)
	{
		goto __buffer_exit;
	}
	
	if(dest_name == NULL)
	{	
		dest_name = unpack_ctx->rbl_header.app_part_name;
	}
	if( (mode & FUPDATE_MODE_DEST_FAL) == FUPDATE_MODE_DEST_FAL)
	{
		dest_interface = fstorage_fal_open(dest_name, FSTORAGE_READWRITE); //open fal
	}else
	if( (mode & FUPDATE_MODE_DEST_FS) == FUPDATE_MODE_DEST_FS)
	{
#if (FBOOT_USING_FILESYSTEM == 1)
		dest_interface = fstorage_fs_open(dest_name, FSTORAGE_READWRITE | FSTORAGE_CREATE_NEW); //open fs
#endif
	}
	if(dest_interface == NULL)
	{
		LOG_NOT_EXIST(dest_name );
		ret =  RBL_UNPACK_ERR_OPEN;
		goto __dest_exit;
	}
	unpack_ctx->target_interface = dest_interface;
	
	ret = rbl_unpack_body_output(unpack_ctx);
	
	if( (flags & FUPDATE_FLAGS_CHECK_VERSION)  == FUPDATE_FLAGS_CHECK_VERSION)
	{
		if(ret > 0)
		{
			rbl_unpack_header_version_update(unpack_ctx);
		}
	}
	
__dest_exit:
	if(dest_interface != NULL)
	{
		if( (mode & FUPDATE_MODE_DEST_FAL) == FUPDATE_MODE_DEST_FAL)
		{
			fstorage_fal_close(dest_interface); //open fal
		}else
		if( (mode & FUPDATE_MODE_DEST_FS) == FUPDATE_MODE_DEST_FS)
		{
	#if (FBOOT_USING_FILESYSTEM == 1)
			fstorage_fs_close(dest_interface); //open fs
	#endif
		}
	}
	
__buffer_exit:
	if(unpack_ctx != NULL)
	{
		rbl_unpack_context_buffer_deinit(unpack_ctx);
	}
	
__src_exit:
	if(src_interface != NULL )
	{
		if( (mode & FUPDATE_MODE_SRC_FAL) == FUPDATE_MODE_SRC_FAL)
		{
			fstorage_fal_close(src_interface); //open fal
		}else
		if( (mode & FUPDATE_MODE_SRC_FS) == FUPDATE_MODE_SRC_FS)
		{
	#if (FBOOT_USING_FILESYSTEM == 1)
			fstorage_fs_close(src_interface); //open fs
	#endif
		}
	}
	if(unpack_ctx != NULL )
	{
		rbl_unpack_context_delete(unpack_ctx);
	}
	return ret;
}


int fupdate_rblcheck(const char* src_name, uint32_t mode)
{
	int ret = 0;
	rbl_unpack_context_t * unpack_ctx = NULL;
	fstorage_interface_t * src_interface = NULL;
	
	if( (mode & FUPDATE_MODE_SRC_FAL) == FUPDATE_MODE_SRC_FAL)
	{
		src_interface = fstorage_fal_open(src_name, 1); //open fal
	}else
	if( (mode & FUPDATE_MODE_SRC_FS) == FUPDATE_MODE_SRC_FS)
	{
#if (FBOOT_USING_FILESYSTEM == 1)
		src_interface = fstorage_fs_open(src_name, 1); //open fs
#endif
	}
	if(src_interface == NULL)
	{
		LOG_NOT_EXIST(src_name);
		ret =  RBL_UNPACK_ERR_OPEN;
		goto __src_exit;
	}
	
	unpack_ctx = rbl_unpack_context_create();
	if(unpack_ctx == NULL)
	{
		ret =  RBL_UNPACK_ERR_NO_MEM;
		goto __src_exit;
	}
	unpack_ctx->src_interface = src_interface;
	
	ret = fstorage_read(unpack_ctx->src_interface, 0,  &(unpack_ctx->rbl_header) , sizeof(unpack_ctx->rbl_header));
	if(ret != sizeof(unpack_ctx->rbl_header))
	{
		ret =  RBL_UNPACK_ERR_READ;
		goto __src_exit;
	}
	
	ret = rbl_unpack_header_check( &(unpack_ctx->rbl_header));
	LOG_I("check %s header rc:%d.", src_name, ret);
	if(ret <= 0)
	{
		goto __src_exit;
	}
	
	rbl_unpack_header_show( &(unpack_ctx->rbl_header));
		
	ret = rbl_unpack_context_buffer_init(unpack_ctx);
	if(ret < 0)
	{
		goto __buffer_exit;
	}
	
	ret = rbl_unpack_body_check(unpack_ctx);
	if(ret < 0)
	{
		goto __buffer_exit;
	}
	
__buffer_exit:
	if(unpack_ctx != NULL)
	{
		rbl_unpack_context_buffer_deinit(unpack_ctx);
	}
	
__src_exit:
	if(src_interface != NULL )
	{
		if( (mode & FUPDATE_MODE_SRC_FAL) == FUPDATE_MODE_SRC_FAL)
		{
			fstorage_fal_close(src_interface); //open fal
		}else
		if( (mode & FUPDATE_MODE_SRC_FS) == FUPDATE_MODE_SRC_FS)
		{
	#if (FBOOT_USING_FILESYSTEM == 1)
			fstorage_fs_close(src_interface); //open fs
	#endif
		}
	}
	if(unpack_ctx != NULL )
	{
		rbl_unpack_context_delete(unpack_ctx);
	}
	return ret;
}

int fupdate_rblprobe(const char* src_name, uint32_t mode)
{	int ret = 0;
	rbl_unpack_context_t * unpack_ctx = NULL;
	fstorage_interface_t * src_interface = NULL;
	
	if( (mode & FUPDATE_MODE_SRC_FAL) == FUPDATE_MODE_SRC_FAL)
	{
		src_interface = fstorage_fal_open(src_name, 1); //open fal
	}else
	if( (mode & FUPDATE_MODE_SRC_FS) == FUPDATE_MODE_SRC_FS)
	{
#if (FBOOT_USING_FILESYSTEM == 1)
		src_interface = fstorage_fs_open(src_name, 1); //open fs
#endif
	}
	if(src_interface == NULL)
	{
		LOG_NOT_EXIST(src_name);
		ret =  RBL_UNPACK_ERR_OPEN;
		goto __src_exit;
	}
	
	unpack_ctx = rbl_unpack_context_create();
	if(unpack_ctx == NULL)
	{
		ret =  RBL_UNPACK_ERR_NO_MEM;
		goto __src_exit;
	}
	unpack_ctx->src_interface = src_interface;
	
	ret = fstorage_read(unpack_ctx->src_interface, 0,  &(unpack_ctx->rbl_header) , sizeof(unpack_ctx->rbl_header));
	if(ret != sizeof(unpack_ctx->rbl_header))
	{
		ret =  RBL_UNPACK_ERR_READ;
		goto __src_exit;
	}
	
	ret = rbl_unpack_header_check( &(unpack_ctx->rbl_header));
	LOG_I("check %s header rc:%d.", src_name, ret);
	if(ret <= 0)
	{
		goto __src_exit;
	}
	
	rbl_unpack_header_show( &(unpack_ctx->rbl_header));
	
__src_exit:
	if(src_interface != NULL )
	{
		if( (mode & FUPDATE_MODE_SRC_FAL) == FUPDATE_MODE_SRC_FAL)
		{
			fstorage_fal_close(src_interface); //open fal
		}else
		if( (mode & FUPDATE_MODE_SRC_FS) == FUPDATE_MODE_SRC_FS)
		{
	#if (FBOOT_USING_FILESYSTEM == 1)
			fstorage_fs_close(src_interface); //open fs
	#endif
		}
	}
	if(unpack_ctx != NULL )
	{
		rbl_unpack_context_delete(unpack_ctx);
	}
	return ret;
}


#endif



